package com.dnjn.happiness.survey.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dnjn.happiness.biz.api.RemoteCommunicateService;
import com.dnjn.happiness.common.core.constant.SecurityConstants;
import com.dnjn.happiness.common.core.domain.R;
import com.dnjn.happiness.common.core.model.SysJobVO;
import com.dnjn.happiness.common.core.utils.StringUtils;
import com.dnjn.happiness.common.core.utils.bean.BeanUtils;
import com.dnjn.happiness.common.security.utils.SecurityUtils;
import com.dnjn.happiness.job.api.RemoteJobService;
import com.dnjn.happiness.survey.api.model.StatisticalAnalysisModel;
import com.dnjn.happiness.survey.domain.Question;
import com.dnjn.happiness.survey.domain.Survey;
import com.dnjn.happiness.survey.domain.SurveyIntervalScore;
import com.dnjn.happiness.survey.domain.SurveyRecord;
import com.dnjn.happiness.survey.domain.Tiku;
import com.dnjn.happiness.survey.domain.vo.StatisticalAnalysisAppriseVO;
import com.dnjn.happiness.survey.mapper.SurveyMapper;
import com.dnjn.happiness.survey.mapper.SurveyRecordMapper;
import com.dnjn.happiness.survey.service.IQuestionService;
import com.dnjn.happiness.survey.service.ISurveyIntervalScoreService;
import com.dnjn.happiness.survey.service.ISurveyService;
import com.dnjn.happiness.survey.service.ITikuService;
import com.dnjn.happiness.system.api.domain.SysUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;


/**
 * <p>
 * 问卷 服务实现类
 * </p>
 *
 * @author Amber
 * @since 2023-10-04
 */
@Service
public class SurveyServiceImpl extends ServiceImpl<SurveyMapper, Survey> implements ISurveyService {
    public static final String SURVEYSTATUSNO = "N";//未参加
    public static final String SURVEYSTATUSYES = "Y";//已参加
    public static final String TYPECOMMON = "COMMON";//普通问卷
    public static final String TYPECOMMUNICATE = "COMMUNICATE";//沟通问卷

    @Autowired
    private SurveyRecordMapper surveyRecordMapper;


    @Autowired
    private SurveyMapper surveyMapper;

    @Autowired
    private IQuestionService questionService;

    @Autowired
    private RemoteCommunicateService communicateService;

    @Autowired
    private RemoteJobService jobService;

    @Autowired
    private ITikuService tikuService;

    @Autowired
    private ISurveyIntervalScoreService intervalScoreService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int saveSurvey(Survey domain) {
        //拿到当前登录用户作用发起人
        SysUser user = SecurityUtils.getLoginUser().getUser();//获取当前登录用户作为发起者
        domain.setInitiatorId(user.getUserId());
        //判断开始时间 是否在今天之前
        if (domain.getDateStart().isBefore(LocalDateTime.now())) {
            domain.setSurveyStatus("PROCESSING");
        } else {
            domain.setSurveyStatus("READY");
        }

        //先保存问卷
        int count = surveyMapper.insert(domain);
        Long surveyId = domain.getSurveyId();


        //发起问卷的时候 更新沟通表的 surveyId
        if (domain.getCommunicateId() != null) {
            communicateService.updateComSurvyId(surveyId, domain.getCommunicateId(),SecurityConstants.INNER);
            //如果是沟通过来的,只更新survy表的survey_type字段为 COMMUNICATE

            lambdaUpdate().eq(Survey::getSurveyId, surveyId).set(Survey::getSurveyType, TYPECOMMUNICATE).update();
        }
        //保存问卷分值区间信息
        List<SurveyIntervalScore> intervalScoreList = domain.getIntervalScoreList();
        if (null != intervalScoreList && intervalScoreList.size() > 0) {
            for (SurveyIntervalScore surveyIntervalScore : intervalScoreList) {
                if (!ObjectUtils.isEmpty(surveyIntervalScore.getStartScore()) && !ObjectUtils.isEmpty(surveyIntervalScore.getEndScore())) {
                    SurveyIntervalScore intervalScore = new SurveyIntervalScore();
                    intervalScore.setStartScore(surveyIntervalScore.getStartScore());
                    intervalScore.setEndScore(surveyIntervalScore.getEndScore());
                    intervalScore.setResult(surveyIntervalScore.getResult());
                    intervalScore.setSurveyId(domain.getSurveyId());
                    intervalScore.setGrade(surveyIntervalScore.getGrade());
                    intervalScoreService.save(intervalScore);
                }
            }
        }

//--------
        //题目一起添加
        questionService.addQuestion(domain);
//-----
        //指定人员
        if (count != 0) {//遍历保存参加问卷的人的记录

            List<Long> userIds = domain.getUserIds();
            if (userIds != null && !userIds.isEmpty()) {
                userIds.stream().forEach(userid -> {
                    SurveyRecord surveyRecord = new SurveyRecord();
                    surveyRecord.setUserId(userid);
                    surveyRecord.setSurveyId(surveyId);
                    surveyRecord.setRecordStatus(SURVEYSTATUSNO);
                    surveyRecordMapper.insert(surveyRecord);

                });
            }

        }

        return count;


    }

    private void setMinAndMaxScore(Survey domain, List<Long> timuIds) {
        Integer minScore = 0;
        Integer maxScore = 0;
        for (Long tikuId : timuIds) {
            Tiku tiku = tikuService.getById(tikuId);
            if ("select".equals(tiku.getIsSelectPack())) {
                Integer minCount = 0;
                Integer maxCount = 0;
                //多选-最小值-选项中最小的一个值， 最大值 全部选项值加起来
                Integer scoreOptionA = tiku.getScoreOptionA();
                Integer scoreOptionB = tiku.getScoreOptionB();
                Integer scoreOptionC = tiku.getScoreOptionC();
                Integer scoreOptionD = tiku.getScoreOptionD();
                Integer scoreOptionE = tiku.getScoreOptionE();
                Integer scoreOptionF = tiku.getScoreOptionF();
                Integer scoreOptionG = tiku.getScoreOptionG();

                List<Integer> list = new ArrayList<>();
                if (!ObjectUtils.isEmpty(scoreOptionA)) {
                    list.add(scoreOptionA);
                }
                if (!ObjectUtils.isEmpty(scoreOptionB)) {
                    list.add(scoreOptionB);
                }
                if (!ObjectUtils.isEmpty(scoreOptionC)) {
                    list.add(scoreOptionC);
                }
                if (!ObjectUtils.isEmpty(scoreOptionD)) {
                    list.add(scoreOptionD);
                }
                if (!ObjectUtils.isEmpty(scoreOptionE)) {
                    list.add(scoreOptionE);
                }
                if (!ObjectUtils.isEmpty(scoreOptionF)) {
                    list.add(scoreOptionF);
                }
                if (!ObjectUtils.isEmpty(scoreOptionG)) {
                    list.add(scoreOptionG);
                }
                if ("Y".equals(tiku.getIsMultipleChoice())) {
                    minCount = Collections.min(list);
                    minScore += minCount;
                    maxCount = list.stream().mapToInt(item -> item).sum();
                    maxScore += maxCount;
                }
                //单选-计算每个选项的 最小值，最大值
                if ("N".equals(tiku.getIsMultipleChoice())) {
                    minCount = Collections.min(list);
                    minScore += minCount;
                    maxCount = Collections.max(list);
                    maxScore += maxCount;
                }
            }
        }
        domain.setMinScore(minScore);
        domain.setMaxScore(maxScore);
    }

    @Override
    public Page<Survey> selectPageSurvey(Survey domain, Page page) {
        return surveyMapper.selectPageSurvey(domain, page);
    }

    @Override
    public Page<Survey> selectPageSurvey1(Survey domain, Page page) {
        if (StringUtils.isEmpty(domain.getSurveyStatus())) {
            domain.setSurveyStatus(null);
        }
        Page<Survey> surveyPage = surveyMapper.selectPageSurvey1(domain, page);
        if (!CollectionUtils.isEmpty(surveyPage.getRecords())) {
            for (Survey survey : surveyPage.getRecords()) {
                Long count = surveyRecordMapper.selectCount(Wrappers.lambdaQuery(SurveyRecord.class).eq(SurveyRecord::getSurveyId, survey.getSurveyId()).eq(SurveyRecord::getRecordStatus, "Y"));
                survey.setCount(count);
            }
        }
        return surveyPage;
    }

    @Override
    public void endSurveyId(Long surveyId) {
        surveyMapper.endSurveyId(surveyId);
    }

    @Override
    public void issuedSurveyId(Long surveyId) {
        surveyMapper.issuedSurveyId(surveyId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateSurvey(Survey domain) {
        Survey oldDto = baseMapper.selectById(domain);
        //拿到当前登录用户作用发起人
//        SysUser user = SecurityUtils.getLoginUser().getUser();//获取当前登录用户作为发起者
        //判断开始时间 是否在今天之前
        if (domain.getDateStart().isBefore(LocalDateTime.now())) {
            domain.setSurveyStatus("PROCESSING");
        } else {
            domain.setSurveyStatus("READY");
        }
        //先保存问卷
        int i = surveyMapper.updateById(domain);
        Long surveyId = domain.getSurveyId();

        //更新区间信息
        intervalScoreService.deleteBySurveyId(domain.getSurveyId());
        List<SurveyIntervalScore> intervalScoreList = domain.getIntervalScoreList();
        if (null != intervalScoreList && intervalScoreList.size() > 0) {
            for (SurveyIntervalScore surveyIntervalScore : intervalScoreList) {
                if (!ObjectUtils.isEmpty(surveyIntervalScore.getStartScore()) && !ObjectUtils.isEmpty(surveyIntervalScore.getEndScore())) {
                    SurveyIntervalScore intervalScore = new SurveyIntervalScore();
                    intervalScore.setStartScore(surveyIntervalScore.getStartScore());
                    intervalScore.setEndScore(surveyIntervalScore.getEndScore());
                    intervalScore.setResult(surveyIntervalScore.getResult());
                    intervalScore.setSurveyId(domain.getSurveyId());
                    intervalScore.setGrade(surveyIntervalScore.getGrade());
                    intervalScoreService.save(intervalScore);
                }
            }
        }

        questionService.remove(Wrappers.lambdaQuery(Question.class).eq(Question::getSurveyId, surveyId));
        questionService.addQuestion(domain);
        surveyRecordMapper.delete(Wrappers.lambdaQuery(SurveyRecord.class).eq(SurveyRecord::getSurveyId, surveyId));
        List<Long> userIds = domain.getUserIds();
        if (!CollectionUtils.isEmpty(userIds) && userIds.size() > 0) {
            userIds.stream().forEach(userid -> {
                SurveyRecord surveyRecord = new SurveyRecord();
                surveyRecord.setUserId(userid);
                surveyRecord.setSurveyId(surveyId);
                surveyRecord.setRecordStatus(SURVEYSTATUSNO);
                surveyRecordMapper.insert(surveyRecord);
            });
        }
        return i;
    }

    @Override
    public void endTime(Survey domain) throws Exception {

        String dayOfYear = String.valueOf(domain.getDateEnd().getYear());//年
        String month = String.valueOf(domain.getDateEnd().getMonthValue());//月
        // 今天是周几（返回的是个枚举类型，需要再getValue()）
        String dayofWeek = String.valueOf(domain.getDateEnd().getDayOfWeek().getValue());//周几
        String dayofMonth = String.valueOf(domain.getDateEnd().getDayOfMonth());//几号
        String hour = String.valueOf(domain.getDateEnd().getHour());//小时
        String minute = String.valueOf(domain.getDateEnd().getMinute());//分钟
        String second = String.valueOf(domain.getDateEnd().getSecond());//秒


        String cronStr = second + " " + minute + " " + hour + " " + dayofMonth + " " + month + " " + "?" + " " + dayOfYear;
        SysJobVO job = new SysJobVO();
        job.setJobGroup("surveyHandler");
        job.setJobName("surveyHandler" + domain.getSurveyId().toString());
        job.setCronExpression(cronStr);
        job.setInvokeTarget("surveyHandler.theSurveyToEnd('" + domain.getSurveyId().toString() + "')");
        job.setCreateBy(SecurityUtils.getUsername());
        job.setMisfirePolicy("3");
        job.setStatus("0");
        jobService.insertJob(job, SecurityConstants.INNER);
        job.setInvokeTarget("surveyHandler.theSurveyToEnd('" + domain.getSurveyId().toString() + "','" + job.getJobId().toString() + "' )");
        jobService.updateJob(job, SecurityConstants.INNER);
        R<SysJobVO> result = jobService.getInfoById(job.getJobId(), SecurityConstants.INNER);
        SysJobVO newJob = new SysJobVO();
        if (StringUtils.isNotNull(result) && StringUtils.isNotNull(result.getData())) {
            newJob = result.getData();
        }
        newJob.setStatus("0");
        SysJobVO sysJobVO = new SysJobVO();
        BeanUtils.copyBeanProp(sysJobVO, newJob);
        jobService.changeStatusApi(sysJobVO, SecurityConstants.INNER);
    }

    @Override
    public void startTime(Survey domain) throws Exception {
        String dayOfYear = String.valueOf(domain.getDateStart().getYear());//年
        String month = String.valueOf(domain.getDateStart().getMonthValue());//月
        // 今天是周几（返回的是个枚举类型，需要再getValue()）
        String dayofWeek = String.valueOf(domain.getDateStart().getDayOfWeek().getValue());//周几
        String dayofMonth = String.valueOf(domain.getDateStart().getDayOfMonth());//几号
        String hour = String.valueOf(domain.getDateStart().getHour());//小时
        String minute = String.valueOf(domain.getDateStart().getMinute());//分钟
        String second = String.valueOf(domain.getDateStart().getSecond());//秒

        String cronStr = second + " " + minute + " " + hour + " " + dayofMonth + " " + month + " " + "?" + " " + dayOfYear;
        SysJobVO job = new SysJobVO();
        job.setJobGroup("surveyHandler");
        job.setJobName("surveyHandler" + domain.getSurveyId().toString());
        job.setCronExpression(cronStr);
        job.setInvokeTarget("surveyHandler.theSurveyToStart('" + domain.getSurveyId().toString() + "')");
//            job.setInvokeTarget("workforceTask.handleWorkforceshift");
        job.setCreateBy(SecurityUtils.getUsername());
        job.setMisfirePolicy("3");
        job.setStatus("0");
        jobService.insertJob(job, SecurityConstants.INNER);
        job.setInvokeTarget("surveyHandler.theSurveyToStart('" + domain.getSurveyId().toString() + "','" + job.getJobId().toString() + "' )");
        jobService.updateJob(job, SecurityConstants.INNER);
        R<SysJobVO> result = jobService.getInfoById(job.getJobId(), SecurityConstants.INNER);
        if (StringUtils.isNotNull(result) && StringUtils.isNotNull(result.getData())) {
            jobService.changeStatusApi(result.getData(), SecurityConstants.INNER);
        }
    }

    @Override
    public Boolean deleteSurvey(Long surveyId) {
        return lambdaUpdate().set(Survey::getDeleted, "1").eq(Survey::getSurveyId, surveyId).update();
    }

    @Override
    public Page<SurveyRecord> selectSurveyRecordByUserId(Long userId, Page page) {
        return baseMapper.selectSurveyRecordByUserId(userId, page);
    }

    @Override
    public List<StatisticalAnalysisModel> selectStatisticalAnalysisSurvryList(StatisticalAnalysisAppriseVO vo) {
        return baseMapper.selectStatisticalAnalysisSurvryList(vo);
    }

    @Override
    public List<Survey> querySvrveyAllByUserId(Long userId) {
        List<Survey> list = baseMapper.querySvrveyAllByUserId(userId);
        if (CollectionUtils.isEmpty(list)) {
            return list;
        }
        for (Survey survey : list) {
            if (Objects.isNull(survey.getGrade())) {
                continue;
            }
            SurveyIntervalScore dto = intervalScoreService.lambdaQuery().eq(SurveyIntervalScore::getSurveyId, survey.getSurveyId()).eq(SurveyIntervalScore::getGrade, survey.getGrade()).one();
            if (!Objects.isNull(dto)) {
                survey.setResult(dto.getResult());
            }
        }
        return list;
    }
}
